#ifndef _M_LOOPER_H  
#define _M_LOOPER_H  
  
#include "util.hpp"  
#include <vector>  
#include <thread>  
#include <mutex>  
#include <atomic>  
#include <condition_variable>  
#include <functional>  
#include <memory>
#include "buffer.hpp"  
  
namespace dhylog  
{   
    enum class AsyncType
    {
        ASYNC_SAFE,
        ASYNC_UNSAFE
    };
    using Functor = std::function<void(Buffer &buffer)>;  
    class AsyncLooper  
    {  
    public:      
        using ptr = std::shared_ptr<AsyncLooper>;  
        AsyncLooper(const Functor&callBack,AsyncType lopper_type=AsyncType::ASYNC_SAFE): 
            _stop(false),
            _thread(std::thread(&AsyncLooper::threadEntry,this)),
            _lopper_type(lopper_type),
            _callBack(callBack){}  
        ~AsyncLooper(){stop();}
        void stop()
        {
            _stop=true;//将退出标志设置为true
            _cond_con.notify_all();//唤醒所有工作线程
            _thread.join();//等待工作线程退出
        }  
        void push(const char* data, size_t len) 
        {           
            //1.无限扩容-非安全   2.固定大小--生产缓冲区中数据满了就阻塞
            std::unique_lock<std::mutex> lock(_mutex);
            //条件变量空值，若缓冲区生于空间大于数据长度，则可以
            if(_lopper_type==AsyncType::ASYNC_SAFE)
                _cond_pro.wait(lock,[&](){return _pro_buffer.writeAbleSize()>=len;});
            //能够走下来代表满足了条件，可以向缓冲区添加数据
            _pro_buffer.push(data,len);   
            //唤醒消费者对缓冲区的数据进行处理
            _cond_con.notify_one();
        }
  
    private:  
        void threadEntry()// 线程入口函数
        {
            while(1)
            {
                //为互斥锁设置一个生命周期，当缓冲区交换完毕后就解锁（并不对数据的处理过程加锁保护）
                {
                    //1.判断生产缓冲区有没有数据，有则交换，无则阻塞
                    std::unique_lock<std::mutex> lock(_mutex);
                    _cond_con.wait(lock,[&](){return _stop||!_pro_buffer.empty();});
                    //退出标记被设置 缓冲区无数据
                    if(_stop&&_pro_buffer.empty()) break;
                    _con_buffer.swap(_pro_buffer);
                    //2.唤醒生产者
                     if(_lopper_type==AsyncType::ASYNC_SAFE)
                        _cond_pro.notify_all();
                }
                //3.被唤醒后，对消费缓冲区进行数据处理
                _callBack(_con_buffer);
                //4.初始化消费缓冲区
                _con_buffer.reset();
            }
        }  
  
    private:  
        AsyncType _lopper_type;
        Functor _callBack; // 具体对缓冲区数据进行处理的回调函数  
        std::atomic<bool> _stop; // 工作器停止标志  
        Buffer _pro_buffer; // 生产缓冲区  
        Buffer _con_buffer; // 消费缓冲区  
        std::mutex _mutex;  
        std::condition_variable _cond_pro; 
        std::condition_variable _cond_con;
        std::thread _thread;//异步工作器对应的工作线程  
    };  
}  
  
#endif